home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / plane / _Segment1.c.ORG < prev    next >
Encoding:
Text File  |  1994-11-16  |  5.8 KB  |  262 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _Segment1.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //#include <LEDA/line.h>
  17.  
  18. #include <LEDA/Segment1.h>
  19. #include <math.h>
  20. #include <ctype.h>
  21.  
  22. //static const double eps = 1e-10;
  23.  
  24.  
  25. //------------------------------------------------------------------------------
  26. // Segments 
  27. //------------------------------------------------------------------------------
  28.  
  29. Segment_rep::Segment_rep()  { count = 1; }
  30.  
  31. Segment_rep::Segment_rep(const Point& p, const Point& q) 
  32. { start = p;
  33.   end   = q;
  34.   dx = q.X()*p.W() - p.X()*q.W();
  35.   dy = q.Y()*p.W() - p.Y()*q.W();
  36.   count = 1; 
  37.     
  38. }
  39.   
  40.  
  41.  
  42. Segment::Segment() { PTR = new Segment_rep; }
  43.  
  44. Segment::Segment(const Point& x, const Point& y) 
  45. { PTR = new Segment_rep(x,y); }
  46.  
  47. Segment::Segment(const Int& x1, const Int& y1, const Int& x2, const Int& y2) 
  48. { PTR = new Segment_rep(Point(x1,y1), Point(x2,y2)); }
  49.  
  50.  
  51. /*
  52. Segment::Segment(const Point& p, double alpha, double length)
  53. { Point q = p.translate(alpha,length);
  54.   PTR  = new Segment_rep(p,q); 
  55.  }
  56.   
  57. Segment Segment::translate(double alpha, double d) const
  58. { Point p = ptr()->start.translate(alpha,d);
  59.   Point q = ptr()->end.translate(alpha,d);
  60.   return Segment(p,q);
  61.  }
  62.  
  63. Segment Segment::translate(const vector& v) const
  64. { Point p = ptr()->start.translate(v);
  65.   Point q = ptr()->end.translate(v);
  66.   return Segment(p,q);
  67.  }
  68.  
  69. */
  70.  
  71.  
  72. ostream& operator<<(ostream& out, const Segment& s) 
  73. { out << "[" << s.start() << "===" << s.end() << "]"; 
  74.   return out;
  75.  } 
  76.  
  77. /*
  78. istream& operator>>(istream& in, Segment& s) 
  79. { int x1,x2,y1,y2; 
  80.   in >> x1 >> y1 >> x2 >> y2; 
  81.   s = Segment(Point(x1,y1),Point(x2,y2)); 
  82.   return in; 
  83.  } 
  84. */
  85.  
  86. istream& operator>>(istream& in, Segment& s) 
  87. { // syntax: {[} p {===} q {]}
  88.  
  89.   Point p,q; 
  90.   char c;
  91.  
  92.   do in.get(c); while (isspace(c));
  93.   if (c != '[') in.putback(c);
  94.  
  95.   in >> p;
  96.  
  97.   do in.get(c); while (isspace(c));
  98.   while (c== '=') in.get(c);
  99.   while (isspace(c)) in.get(c);
  100.   in.putback(c);
  101.  
  102.   in >> q; 
  103.  
  104.   do in.get(c); while (c == ' ');
  105.   if (c != ']') in.putback(c);
  106.  
  107.   s = Segment(p,q); 
  108.   return in; 
  109.  
  110.  } 
  111.  
  112.  
  113. /*
  114. double Segment::angle(const Segment& s) const
  115. {
  116.   double cosfi,fi,norm;
  117.   
  118.   double dx  = ptr()->end.ptr()->x - ptr()->start.ptr()->x; 
  119.   double dy  = ptr()->end.ptr()->y - ptr()->start.ptr()->y; 
  120.  
  121.   double dxs = s.ptr()->end.ptr()->x - s.ptr()->start.ptr()->x; 
  122.   double dys = s.ptr()->end.ptr()->y - s.ptr()->start.ptr()->y; 
  123.   
  124.   cosfi=dx*dxs+dy*dys;
  125.   
  126.   norm=(dx*dx+dy*dy)*(dxs*dxs+dys*dys);
  127.  
  128.   if (norm == 0) return 0;
  129.  
  130.   cosfi /= sqrt( norm );
  131.  
  132.   if (cosfi >=  1.0 ) return 0;
  133.   if (cosfi <= -1.0 ) return M_PI;
  134.   
  135.   fi=acos(cosfi);
  136.  
  137.   if (dx*dys-dy*dxs>0) return fi;
  138.  
  139.   return -fi;
  140.  
  141. }
  142.  
  143.  
  144. double Segment::distance(const Segment& s) const
  145. { if (angle(s)!=0) return 0;
  146.   return distance(s.ptr()->start);
  147.  }
  148.  
  149. double  Segment::distance() const
  150. { return distance(Point(0,0)); }
  151.  
  152. double Segment::distance(const Point& p) const
  153. { Segment s(ptr()->start,p);
  154.   double l = s.length();
  155.   if (l==0) return 0;
  156.   else return l*sin(angle(s));
  157.  }
  158.  
  159.  
  160. double  Segment::y_proj(double x)  const
  161. { return  ptr()->start.ptr()->y - ptr()->slope * (ptr()->start.ptr()->x - x); }
  162.  
  163. double  Segment::x_proj(double y)  const
  164. { if (vertical())  return  ptr()->start.ptr()->x;
  165.   return  ptr()->start.ptr()->x - (ptr()->start.ptr()->y - y)/ptr()->slope; }
  166.  
  167. */
  168.  
  169. bool Segment::intersection(const Segment& s, Point& inter) const
  170. /* decides whether |s| and |this| segment intersect and, if so, returns the
  171. intersection in |r|. It is assumed that both segments have non-zero length */
  172. Int px = ptr()->start.X();
  173. Int py = ptr()->start.Y();
  174. Int pw = ptr()->start.W();
  175.  
  176. Int qx = ptr()->end.X();
  177. Int qy = ptr()->end.Y();
  178. Int qw = ptr()->end.W();
  179.  
  180. Int spx = s.start().X();
  181. Int spy = s.start().Y();
  182. Int spw = s.start().W();
  183.  
  184. Int sqx = s.end().X();
  185. Int sqy = s.end().Y();
  186. Int sqw = s.end().W();
  187.  
  188. Int A = -(py*qw - qy*pw);
  189. Int B =   px*qw - qx*pw;
  190. Int C = -(px*qy - qx*py);
  191.  
  192.  
  193. Int Aprime = -(spy*sqw - sqy*spw);
  194. Int Bprime =   spx*sqw - sqx*spw;
  195. Int Cprime = -(spx*sqy - sqx*spy);
  196.  
  197. Int cx = -(B*Cprime - C*Bprime);
  198. Int cy =   A*Cprime - C*Aprime ;
  199. Int cw = -(A*Bprime - B*Aprime);
  200.  
  201. if (cw == 0) return false;   //same slope
  202.  
  203. inter = Point(cx,cy,cw);
  204.  
  205.  
  206. /* cw is non-zero. Its sign does not matter for the test to follow.
  207.  
  208.   
  209.   if (pX*cw < cx &&  qX*cw < cx ||  pX*cw > cx  && qX*cw > cx ||
  210.    spX*cw< cx && sqX*cw < cx || spX*cw > cx && sqX*cw > cx ||
  211.    pY*cw < cy &&  qY*cw < cy ||  pY*cw > cy  && qY*cw > cy ||
  212.    spY*cw< cy && sqY*cw < cy || spY*cw > cy && sqY*cw > cy)
  213.   return false;
  214. */
  215.  
  216. /* we still need to test whether inter lies on both segments. A point lies on a segment if it compares diffently with the two endpoints of the segment */
  217.  
  218. if ((compare(start(),inter) == compare(end(),inter)) ||
  219.  (compare(s.start(),inter) == compare(s.end(),inter)))
  220. return false;
  221.  
  222. return true;
  223. }
  224.  
  225.  
  226. bool Segment::intersection_of_lines(const Segment& s, Point& inter) const
  227.   /* decides whether the lines induced by |s| and |this| segment 
  228.      intersect and, if so, returns the intersection in |inter|. 
  229.      It is assumed that both segments have non-zero length
  230.    */
  231.   
  232.   Int w = dy()*s.dx() - dx()*s.dy();
  233.  
  234.   if (w == 0) return false;   //same slope
  235.  
  236.   Int c1 = X2()*Y1() - X1()*Y2();
  237.   Int c2 = s.X2()*s.Y1() - s.X1()*s.Y2();
  238.  
  239.   inter = Point(dx()*c2 - s.dx()*c1, dy()*c2 - s.dy()*c1, w);
  240.  
  241.   return true;
  242. }
  243.  
  244. /*
  245. Segment Segment::rotate(double alpha) const
  246. {  double  l = length();
  247.    Point p = start();
  248.    double beta = alpha + angle();
  249.    return Segment(p,beta,l);
  250. }
  251.  
  252. Segment Segment::rotate(const Point& origin, double alpha) const
  253. {  Point p = start().rotate(origin,alpha);
  254.    Point q = end().rotate(origin,alpha);
  255.    return Segment(p,q);
  256. }
  257. */
  258.  
  259.